package com.zwps.common.controller.advice;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import com.github.pagehelper.Page;
import com.zwps.common.controller.constant.SwaggerConstant;
import com.zwps.common.controller.response.message.ResponseDataMessage;
import com.zwps.common.controller.response.message.ResponseDataPageMessage;
import com.zwps.common.controller.response.message.ResponseMessage;
import com.zwps.common.core.constant.FeignConstant;
import com.zwps.extra.http.response.message.InterfaceResponseMessage;

import cn.hutool.core.util.StrUtil;

@ControllerAdvice
public class ResponseBeanAdvice implements ResponseBodyAdvice<Object> {

    private final AntPathMatcher matcher = new AntPathMatcher();

    @Value("${server.servlet.context-path:/}")
    private String serverContextPath;
    
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
                                  ServerHttpResponse response) {

        String path = request.getURI().getPath();
        // 排除spring admin 的健康检查响应数据做处理
        if (path.startsWith("/actuator")) {
            return body;
        } else {
            String pattern = SwaggerConstant.ANT_PATH_V3_API_DOC;
            if (!(StrUtil.isEmpty(serverContextPath) || "/".equals(serverContextPath))) {
                pattern = serverContextPath + pattern;
            }
            if (matcher.match(pattern, path)) {
                return body;
            }
        }

        if (returnType.getContainingClass() == BasicErrorController.class) { // springboot 异常controller
            if (body instanceof LinkedHashMap) {
                @SuppressWarnings("unchecked")
                LinkedHashMap<String, Object> linkedHashMap = (LinkedHashMap<String, Object>) body;
                linkedHashMap.put("message", linkedHashMap.get("error"));
                return body;
            }
            return ResponseMessage.serverExceptionMessage();
        }

        if (returnType.getMethod().getReturnType() == void.class) {
            return ResponseMessage.successMessage();
        }

        if (body instanceof InterfaceResponseMessage) {
            // 如果是Feign请求，请求出现异常时，需要将响应码设置为400，以便调用者处理Feign异常，触发进入对应的异常处理代码
            if (!((InterfaceResponseMessage<?>) body).isSuccess()
                    && null != request.getHeaders().get(FeignConstant.HEADER_FEIGN_REQUEST)) {
                response.setStatusCode(HttpStatus.BAD_REQUEST);
            }
            return body;
        }

        if (body instanceof String) {
            return body;
        }

        if (body instanceof Page) {
            return ResponseDataPageMessage.data((Page<?>) body);
        }
        return ResponseDataMessage.data( formatBigDecimalValues(body));
    }


    public Object formatBigDecimalValues(Object obj) {
        // 获取对象的所有字段
        Field[] fields = obj.getClass().getDeclaredFields();

        for (Field field : fields) {
            field.setAccessible(true); // 设置字段为可访问

            try {
                Object value = field.get(obj); // 获取字段值

                // 检查字段类型是否是 BigDecimal
               /* if (value instanceof BigDecimal) {
                    BigDecimal bigDecimalValue = (BigDecimal) value;
                    // 在这里你可以处理 BigDecimal，比如格式化它
                    field.set(obj, formatBigDecimal(bigDecimalValue)); // 更新字段值
                }*/
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return obj; // 返回更新后的对象
    }

    // 格式化BigDecimal保留两位小数
  /*  private BigDecimal formatBigDecimal(BigDecimal value) {
        return value.setScale(2, BigDecimal.ROUND_HALF_UP); // 保证两位小数
    }*/

}
